package com.hm.shopping.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.stereotype.Service;

import com.hm.common.def.DataStatusDef;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.su.bean.PageInfo;
import com.hm.common.su.bean.PageInfo.PageInfoParam;
import com.hm.common.util.ArraysUtil;
import com.hm.common.util.CommonUtil;
import com.hm.shopping.auto.su.BaseDomain;
import com.hm.shopping.domain.GoodsIntroductionDomain;
import com.hm.shopping.domain.QShopcartDomain;
import com.hm.shopping.domain.ShopcartDomain;
import com.hm.shopping.repository.GoodsIntroductionRepository;
import com.hm.shopping.repository.ShopcartRepository;
import com.hm.shopping.su.BeanUtil;
import com.hm.shopping.vo.GoodsIntroductionVo;
import com.hm.shopping.vo.ShopcartVo;

/**
 * @author shishun.wang
 * @date 2018年2月9日 下午4:27:50
 * @version 1.0
 * @describe
 */
@Service
public class ShopcartServiceImpl implements ShopcartService {

	@Autowired
	private ShopcartRepository shopcartRepository;

	@Autowired
	private GoodsIntroductionService goodsIntroductionService;

	@Autowired
	private GoodsIntroductionRepository goodsIntroductionRepository;

	@Override
	public void joinShopcart(String goodsId, String buyerId, List<String> goodsAttributes, Integer quantity) {
		if (CommonUtil.isAnyEmpty(goodsId, buyerId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		GoodsIntroductionDomain goodsIntroduction = goodsIntroductionRepository.findOne(goodsId);
		if (CommonUtil.isEmpty(goodsIntroduction)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND, "商品");
		}

		if (CommonUtil.isEmpty(quantity)) {
			quantity = 1;
		}

		if (CommonUtil.isEmpty(goodsAttributes)) {
			goodsAttributes = new ArrayList<String>();
		}

		QShopcartDomain qShopcartDomain = QShopcartDomain.shopcartDomain;
		AtomicBoolean isNew = new AtomicBoolean(true);
		for (ShopcartDomain item : shopcartRepository.findAll(qShopcartDomain.goodsId.eq(goodsId).and(qShopcartDomain.buyerId.eq(buyerId)).and(qShopcartDomain.status.eq(DataStatusDef.ENABLE)))) {
			if (ArraysUtil.equals(item.getGoodsAttributes(), goodsAttributes)) {
				item.setQuantity(item.getQuantity() + quantity);
				item.setUpdateTime(new Date());
				shopcartRepository.save(item);

				isNew.set(false);
			}
		}

		if (isNew.get()) {
			ShopcartDomain shopcartDomain = new ShopcartDomain();

			shopcartDomain.setBuyerId(buyerId);
			shopcartDomain.setGoodsId(goodsId);
			shopcartDomain.setGoodsAttributes(goodsAttributes);
			shopcartDomain.setQuantity(quantity);
			shopcartDomain.setSelected(true);
			BaseDomain.initBaseInfo(shopcartDomain);

			shopcartRepository.save(shopcartDomain);
		}
	}

	@Override
	public void removeShopcart(String shopcartId) {
		if (CommonUtil.isEmpty(shopcartId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ShopcartDomain shopcartDomain = shopcartRepository.findOne(shopcartId);
		if (CommonUtil.isNotEmpty(shopcartDomain)) {
			shopcartDomain.setStatus(DataStatusDef.DISABLE);
			shopcartRepository.save(shopcartDomain);
		}
	}

	@Override
	@SuppressWarnings("unchecked")
	public PageInfo<ShopcartVo> getShopcartList(PageInfoParam pageParam, String buyerId) {
		if (CommonUtil.isEmpty(buyerId)) {
			return PageInfo.EMPTY;
		}

		QShopcartDomain qShopcartDomain = QShopcartDomain.shopcartDomain;
		Pageable pageable = new QPageRequest(pageParam.getPage(), pageParam.getSize(), qShopcartDomain.createTime.desc());
		Page<ShopcartDomain> page = shopcartRepository.findAll(qShopcartDomain.status.eq(DataStatusDef.ENABLE).and(qShopcartDomain.buyerId.eq(buyerId)), pageable);

		return new PageInfo<ShopcartVo>(page.getContent().parallelStream().map(item -> {
			ShopcartVo vo = new ShopcartVo();
			BeanUtil.copyProperties(item, vo);
			GoodsIntroductionVo goodsIntroductionVo = goodsIntroductionService.getGoodsIntroduction(item.getGoodsId());
			goodsIntroductionVo.setGoodsAttributes(goodsIntroductionVo.getGoodsAttributes().parallelStream().map(attr -> {
				attr.setAttributes(attr.getAttributes().parallelStream().map(attrDetail -> {
					attrDetail.setDefaultSelected(item.getGoodsAttributes().contains(attrDetail.getName()));
					return attrDetail;
				}).collect(Collectors.toList()));

				return attr;
			}).collect(Collectors.toList()));

			vo.setGoodsIntroduction(goodsIntroductionVo);
			return vo;
		}).collect(Collectors.toList()), page.getTotalPages(), page.getTotalElements());
	}

	@Override
	public void addShopcart(String shopcartId, int count) {
		if (CommonUtil.isEmpty(shopcartId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ShopcartDomain shopcartDomain = shopcartRepository.findOne(shopcartId);
		if (CommonUtil.isNotEmpty(shopcartDomain)) {
			shopcartDomain.setQuantity(shopcartDomain.getQuantity() + count);
			if (shopcartDomain.getQuantity() <= 1) {
				return;
			}
			shopcartRepository.save(shopcartDomain);
		}
	}

	@Override
	public void updateShopcartSelected(String shopcartId) {
		if (CommonUtil.isEmpty(shopcartId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ShopcartDomain shopcartDomain = shopcartRepository.findOne(shopcartId);
		if (CommonUtil.isNotEmpty(shopcartDomain)) {
			shopcartDomain.setSelected(!shopcartDomain.isSelected());
			shopcartRepository.save(shopcartDomain);
		}
	}

	@Override
	public long getShopcartGoodsCount(String buyerId) {
		if (CommonUtil.isEmpty(buyerId)) {
			return 0;
		}

		AtomicLong selectedCount = new AtomicLong(0);
		QShopcartDomain qShopcartDomain = QShopcartDomain.shopcartDomain;
		shopcartRepository.findAll(qShopcartDomain.status.eq(DataStatusDef.ENABLE).and(qShopcartDomain.buyerId.eq(buyerId)).and(qShopcartDomain.selected.eq(true))).forEach(item -> {
			selectedCount.addAndGet(item.getQuantity());
		});
		return selectedCount.get();
	}

}
